package main

import "fmt"

func main() {
	// golang中的数组是一种由固定长度和固定对象类型所组成的数据类型
	//	var a [4]int
	//	a[0] = 1
	//	i := a[0]

	// 与数组不同的时，切片在声明时不需要指定元素个数(长度)。切片有两种声明方式：
	//	letters := []string{"a", "b", "c", "d"}

	// 元素类型，切片元素个数，切片容量
	//	var s []byte
	//	s = make([]byte, 5, 5)
	// s == []byte{0, 0, 0, 0, 0}

	// 经常省略容量 容量就默认为元素长度
	//	s := make([]byte, 5)

	// 当切片声明之后，可以通过内置的len函数和cap函数，分别获取切片的元素个数和容量，如下所示：
	//	len(s) == 5
	//	cap(s) == 5

	// 一个已经声明好的切片，是可以再次被切片化
	//	b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
	// b是一个切片，可以通过[n:m]左开右闭的方式基于这个切片再生成一个切片。上图中，b[1:4]就生成了一个新切片，切片元素范围为1,2,3，不包括4.
	// b[1:4] == []byte{'o', 'l', 'a'}, sharing the same storage as b
	// b[:2] == []byte{'g', 'o'}
	// b[2:] == []byte{'l', 'a', 'n', 'g'}
	// b[:] == b

	// golang中允许基于数组生成一个切片
	//	x := [3]string{"Лайка", "Белка", "Стрелка"}
	//	s := x[:] // a slice referencing the storage of x

	//func copy(dst, src []T) int
	//	s := make([]int, 0) // 无初始值的切片
	s := make([]int, 5, 5)
	s = append(s, 1, 2, 3, 4)
	t := make([]int, len(s), (cap(s)+1)*2)
	copy(t, s)
	//	s = t
	fmt.Println(t)
	fmt.Println(s)
	fmt.Println(len(s))
	fmt.Println(cap(s))
	fmt.Println(len(t))
	fmt.Println(cap(t))

	// 当使用append函数时，append函数会判断目的切片是否具有剩余空间，如果没有剩余空间，则会自动扩充两倍空间
	// append函数不只能添加元素，还能将添加切片，如下：
	//	a := []string{"John", "Paul"}
	//	b := []string{"George", "Ringo", "Pete"}
	//	a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
	// a == []string{"John", "Paul", "George", "Ringo", "Pete"}

	f := func(y int) bool {
		return true
	}

	fmt.Println(Filter(s, f))

	// 防止无用数据，一般使用copy切片
}

// Filter returns a new slice holding only
// the elements of s that satisfy f()
func Filter(s []int, fn func(int) bool) []int {
	var p []int // == nil
	for _, v := range s {
		if fn(v) {
			p = append(p, v)
		}
	}
	return p
}
